package com.iecas.test;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

// 坦克大战游戏主类
public class TankWarGam1e extends JFrame {
    public static final int WIDTH = 800;
    public static final int HEIGHT = 600;

    public TankWarGam1e() {
        initUI();
    }

    private void initUI() {
        add(new GamePanel());

        setTitle("坦克大战");
        setSize(WIDTH, HEIGHT);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            TankWarGam1e game = new TankWarGam1e();
            game.setVisible(true);
        });
    }
}

// 游戏面板类
class GamePanel extends JPanel implements ActionListener, KeyListener {
    private static final int DELAY = 15;

    private PlayerTank player;
    private List<EnemyTank> enemies;
    private List<Bullet> bullets;
    private List<Explosion> explosions;
    private List<Wall> walls;

    private Timer timer;
    private boolean[] keys;
    private int score;
    private int lives;
    private boolean gameOver;

    public GamePanel() {
        initGame();
    }

    private void initGame() {
        setBackground(Color.BLACK);
        setPreferredSize(new Dimension(TankWarGam1e.WIDTH, TankWarGam1e.HEIGHT));
        setFocusable(true);

        keys = new boolean[KeyEvent.KEY_LAST + 1];
        addKeyListener(this);

        player = new PlayerTank(375, 500);
        enemies = new ArrayList<>();
        bullets = new ArrayList<>();
        explosions = new ArrayList<>();
        walls = new ArrayList<>();

        score = 0;
        lives = 3;
        gameOver = false;

        createWalls();
        createEnemies();

        timer = new Timer(DELAY, this);
        timer.start();
    }

    private void createWalls() {
        // 创建障碍物
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 3; j++) {
                walls.add(new Wall(100 + i * 60, 200 + j * 30));
            }
        }
    }

    private void createEnemies() {
        Random rand = new Random();
        for (int i = 0; i < 5; i++) {
            enemies.add(new EnemyTank(100 + i * 150, 50, rand.nextInt(4)));
        }
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);

        drawPlayer(g);
        drawEnemies(g);
        drawBullets(g);
        drawWalls(g);
        drawExplosions(g);
        drawInfo(g);
    }

    private void drawPlayer(Graphics g) {
        if (player.isAlive()) {
            g.setColor(Color.GREEN);
            g.fillRect(player.getX(), player.getY(), 30, 30);

            // 绘制炮管
            g.setColor(Color.DARK_GRAY);
            switch (player.getDirection()) {
                case 0: // 上
                    g.fillRect(player.getX() + 12, player.getY() - 10, 6, 15);
                    break;
                case 1: // 右
                    g.fillRect(player.getX() + 15, player.getY() + 12, 15, 6);
                    break;
                case 2: // 下
                    g.fillRect(player.getX() + 12, player.getY() + 15, 6, 15);
                    break;
                case 3: // 左
                    g.fillRect(player.getX() - 10, player.getY() + 12, 15, 6);
                    break;
            }
        }
    }

    private void drawEnemies(Graphics g) {
        for (EnemyTank enemy : enemies) {
            if (enemy.isAlive()) {
                g.setColor(Color.RED);
                g.fillRect(enemy.getX(), enemy.getY(), 30, 30);

                // 绘制炮管
                g.setColor(Color.DARK_GRAY);
                switch (enemy.getDirection()) {
                    case 0: // 上
                        g.fillRect(enemy.getX() + 12, enemy.getY() - 10, 6, 15);
                        break;
                    case 1: // 右
                        g.fillRect(enemy.getX() + 15, enemy.getY() + 12, 15, 6);
                        break;
                    case 2: // 下
                        g.fillRect(enemy.getX() + 12, enemy.getY() + 15, 6, 15);
                        break;
                    case 3: // 左
                        g.fillRect(enemy.getX() - 10, enemy.getY() + 12, 15, 6);
                        break;
                }
            }
        }
    }

    private void drawBullets(Graphics g) {
        g.setColor(Color.YELLOW);
        for (Bullet bullet : bullets) {
            g.fillOval(bullet.getX(), bullet.getY(), 6, 6);
        }
    }

    private void drawWalls(Graphics g) {
        g.setColor(Color.GRAY);
        for (Wall wall : walls) {
            g.fillRect(wall.getX(), wall.getY(), 30, 30);
        }
    }

    private void drawExplosions(Graphics g) {
        for (Explosion explosion : explosions) {
            g.setColor(Color.ORANGE);
            g.fillOval(explosion.getX(), explosion.getY(), explosion.getSize(), explosion.getSize());
        }
    }

    private void drawInfo(Graphics g) {
        g.setColor(Color.WHITE);
        g.setFont(new Font("Arial", Font.BOLD, 16));
        g.drawString("分数: " + score, 10, 20);
        g.drawString("生命: " + lives, 10, 40);

        if (gameOver) {
            g.setFont(new Font("Arial", Font.BOLD, 36));
            g.drawString("游戏结束!", TankWarGam1e.WIDTH / 2 - 80, TankWarGam1e.HEIGHT / 2);
            g.setFont(new Font("Arial", Font.BOLD, 16));
            g.drawString("按R键重新开始", TankWarGam1e.WIDTH / 2 - 50, TankWarGam1e.HEIGHT / 2 + 40);
        }
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        update();
        repaint();
    }

    private void update() {
        if (gameOver) {
            if (keys[KeyEvent.VK_R]) {
                initGame();
            }
            return;
        }

        // 更新玩家坦克
        if (player.isAlive()) {
            updatePlayer();
        } else {
            lives--;
            if (lives > 0) {
                player.respawn(375, 500);
            } else {
                gameOver = true;
            }
        }

        // 更新敌人坦克
        updateEnemies();

        // 更新子弹
        updateBullets();

        // 更新爆炸效果
        updateExplosions();

        // 检查游戏是否胜利
        if (enemies.isEmpty()) {
            createEnemies();
        }
    }

    private void updatePlayer() {
        int dx = 0;
        int dy = 0;
        int newDirection = player.getDirection();

        if (keys[KeyEvent.VK_UP]) {
            dy = -3;
            newDirection = 0;
        } else if (keys[KeyEvent.VK_RIGHT]) {
            dx = 3;
            newDirection = 1;
        } else if (keys[KeyEvent.VK_DOWN]) {
            dy = 3;
            newDirection = 2;
        } else if (keys[KeyEvent.VK_LEFT]) {
            dx = -3;
            newDirection = 3;
        }

        player.setDirection(newDirection);

        // 检查移动是否会导致碰撞
        if (!checkCollision(player.getX() + dx, player.getY(), player.getDirection())) {
            player.setX(player.getX() + dx);
        }

        if (!checkCollision(player.getX(), player.getY() + dy, player.getDirection())) {
            player.setY(player.getY() + dy);
        }

        // 边界检查
        player.setX(Math.max(0, Math.min(player.getX(), TankWarGam1e.WIDTH - 30)));
        player.setY(Math.max(0, Math.min(player.getY(), TankWarGam1e.HEIGHT - 30)));

        // 发射子弹
        if (keys[KeyEvent.VK_SPACE] && player.canFire()) {
            bullets.add(player.fire());
        }
    }

    private void updateEnemies() {
        Random rand = new Random();

        for (EnemyTank enemy : enemies) {
            if (enemy.isAlive()) {
                // 随机改变方向
                if (rand.nextInt(100) < 2) {
                    enemy.setDirection(rand.nextInt(4));
                }

                // 移动
                int dx = 0;
                int dy = 0;

                switch (enemy.getDirection()) {
                    case 0: dy = -2; break;
                    case 1: dx = 2; break;
                    case 2: dy = 2; break;
                    case 3: dx = -2; break;
                }

                // 检查移动是否会导致碰撞
                if (!checkCollision(enemy.getX() + dx, enemy.getY(), enemy.getDirection())) {
                    enemy.setX(enemy.getX() + dx);
                }

                if (!checkCollision(enemy.getX(), enemy.getY() + dy, enemy.getDirection())) {
                    enemy.setY(enemy.getY() + dy);
                }

                // 边界检查
                enemy.setX(Math.max(0, Math.min(enemy.getX(), TankWarGam1e.WIDTH - 30)));
                enemy.setY(Math.max(0, Math.min(enemy.getY(), TankWarGam1e.HEIGHT - 30)));

                // 发射子弹
                if (rand.nextInt(100) < 3 && enemy.canFire()) {
                    bullets.add(enemy.fire());
                }
            }
        }
    }

    private void updateBullets() {
        List<Bullet> bulletsToRemove = new ArrayList<>();

        for (Bullet bullet : bullets) {
            bullet.move();

            // 检查子弹是否超出边界
            if (bullet.getX() < 0 || bullet.getX() > TankWarGam1e.WIDTH ||
                    bullet.getY() < 0 || bullet.getY() > TankWarGam1e.HEIGHT) {
                bulletsToRemove.add(bullet);
                continue;
            }

            // 检查子弹是否击中墙壁
            boolean hitWall = false;
            for (Wall wall : walls) {
                if (bullet.intersects(wall)) {
                    bulletsToRemove.add(bullet);
                    hitWall = true;
                    break;
                }
            }

            if (hitWall) continue;

            // 检查玩家子弹是否击中敌人
            if (bullet.isPlayerBullet()) {
                for (EnemyTank enemy : enemies) {
                    if (enemy.isAlive() && bullet.intersects(enemy)) {
                        bulletsToRemove.add(bullet);
                        enemy.setAlive(false);
                        explosions.add(new Explosion(enemy.getX(), enemy.getY()));
                        score += 100;
                        break;
                    }
                }
            }
            // 检查敌人子弹是否击中玩家
            else {
                if (player.isAlive() && bullet.intersects(player)) {
                    bulletsToRemove.add(bullet);
                    player.setAlive(false);
                    explosions.add(new Explosion(player.getX(), player.getY()));
                    break;
                }
            }
        }

        // 移除需要删除的子弹
        bullets.removeAll(bulletsToRemove);

        // 移除死亡的敌人
        enemies.removeIf(enemy -> !enemy.isAlive());
    }

    private void updateExplosions() {
        List<Explosion> explosionsToRemove = new ArrayList<>();

        for (Explosion explosion : explosions) {
            explosion.update();
            if (explosion.isFinished()) {
                explosionsToRemove.add(explosion);
            }
        }

        explosions.removeAll(explosionsToRemove);
    }

    private boolean checkCollision(int x, int y, int direction) {
        Rectangle tankRect = new Rectangle(x, y, 30, 30);

        // 检查与墙壁的碰撞
        for (Wall wall : walls) {
            if (tankRect.intersects(wall.getBounds())) {
                return true;
            }
        }

        // 检查与敌人的碰撞（仅玩家需要检查）
        if (direction == player.getDirection() && x == player.getX() && y == player.getY()) {
            for (EnemyTank enemy : enemies) {
                if (enemy.isAlive() && tankRect.intersects(enemy.getBounds())) {
                    return true;
                }
            }
        }

        return false;
    }

    @Override
    public void keyPressed(KeyEvent e) {
        int keyCode = e.getKeyCode();
        keys[keyCode] = true;
    }

    @Override
    public void keyReleased(KeyEvent e) {
        int keyCode = e.getKeyCode();
        keys[keyCode] = false;
    }

    @Override
    public void keyTyped(KeyEvent e) {}
}

// 玩家坦克类
class PlayerTank implements GameObject{
    private int x, y;
    private int direction; // 0:上, 1:右, 2:下, 3:左
    private boolean alive;
    private long lastFireTime;
    private static final long FIRE_DELAY = 500; // 发射延迟(毫秒)

    public PlayerTank(int x, int y) {
        this.x = x;
        this.y = y;
        this.direction = 0;
        this.alive = true;
        this.lastFireTime = 0;
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public void setDirection(int direction) {
        this.direction = direction;
    }

    public int getDirection() {
        return direction;
    }

    public void setAlive(boolean alive) {
        this.alive = alive;
    }

    public boolean isAlive() {
        return alive;
    }

    public void respawn(int x, int y) {
        this.x = x;
        this.y = y;
        this.alive = true;
        this.direction = 0;
    }

    public boolean canFire() {
        long currentTime = System.currentTimeMillis();
        return currentTime - lastFireTime >= FIRE_DELAY;
    }

    public Bullet fire() {
        lastFireTime = System.currentTimeMillis();

        int bulletX = x + 12;
        int bulletY = y + 12;

        return new Bullet(bulletX, bulletY, direction, true);
    }

    public Rectangle getBounds() {
        return new Rectangle(x, y, 30, 30);
    }
}

// 敌人坦克类
class EnemyTank implements GameObject{
    private int x, y;
    private int direction; // 0:上, 1:右, 2:下, 3:左
    private boolean alive;
    private long lastFireTime;
    private static final long FIRE_DELAY = 2000; // 发射延迟(毫秒)

    public EnemyTank(int x, int y, int direction) {
        this.x = x;
        this.y = y;
        this.direction = direction;
        this.alive = true;
        this.lastFireTime = System.currentTimeMillis();
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public void setDirection(int direction) {
        this.direction = direction;
    }

    public int getDirection() {
        return direction;
    }

    public void setAlive(boolean alive) {
        this.alive = alive;
    }

    public boolean isAlive() {
        return alive;
    }

    public boolean canFire() {
        long currentTime = System.currentTimeMillis();
        return currentTime - lastFireTime >= FIRE_DELAY;
    }

    public Bullet fire() {
        lastFireTime = System.currentTimeMillis();

        int bulletX = x + 12;
        int bulletY = y + 12;

        return new Bullet(bulletX, bulletY, direction, false);
    }

    public Rectangle getBounds() {
        return new Rectangle(x, y, 30, 30);
    }
}

// 子弹类
class Bullet {
    private int x, y;
    private int direction; // 0:上, 1:右, 2:下, 3:左
    private boolean playerBullet;
    private static final int SPEED = 6;

    public Bullet(int x, int y, int direction, boolean playerBullet) {
        this.x = x;
        this.y = y;
        this.direction = direction;
        this.playerBullet = playerBullet;
    }

    public void move() {
        switch (direction) {
            case 0: y -= SPEED; break;
            case 1: x += SPEED; break;
            case 2: y += SPEED; break;
            case 3: x -= SPEED; break;
        }
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public boolean isPlayerBullet() {
        return playerBullet;
    }

    public boolean intersects(GameObject obj) {
        Rectangle bulletRect = new Rectangle(x, y, 6, 6);
        return bulletRect.intersects(obj.getBounds());
    }
}

// 爆炸效果类
class Explosion {
    private int x, y;
    private int size;
    private int maxSize;
    private boolean finished;

    public Explosion(int x, int y) {
        this.x = x;
        this.y = y;
        this.size = 10;
        this.maxSize = 60;
        this.finished = false;
    }

    public void update() {
        size += 2;
        if (size >= maxSize) {
            finished = true;
        }
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public int getSize() {
        return size;
    }

    public boolean isFinished() {
        return finished;
    }
}

// 墙壁类
class Wall implements GameObject{
    private int x, y;

    public Wall(int x, int y) {
        this.x = x;
        this.y = y;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public Rectangle getBounds() {
        return new Rectangle(x, y, 30, 30);
    }
}

// 游戏对象接口
interface GameObject {
    Rectangle getBounds();
}